home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / What's New? / Development Kits / Apple Game Sprockets DR1 / Examples / NetSprocketTest / NSTestApp.cp < prev    next >
Encoding:
Text File  |  1996-04-24  |  14.8 KB  |  606 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                              **
  3.  **     Module:        PPTestApp.cp                                             **                        
  4.  **                                                                              **
  5.  **                                                                              **
  6.  **     Purpose:     Test harness for PowerPlay                                 **            
  7.  **                                                                              **
  8.  **        Author:        Jamie Osborne                                              **
  9.  **                                                                              **
  10.  **     Copyright (C) 1996 Apple Computer, Inc.  All rights reserved.         **
  11.  **                                                                              **
  12.  **                                                                              **
  13.  *****************************************************************************/
  14.  
  15. #define VERBOSE 0
  16.  
  17. #include "NSTestApp.h"
  18. #include "CPlayerWindow.h"
  19. #include <LGrowZone.h>
  20. #include <LWindow.h>
  21. #include <PP_Messages.h>
  22. #include <PP_Resources.h>
  23. #include <PPobClasses.h>
  24. #include <UDrawingState.h>
  25. #include <UMemoryMgr.h>
  26. #include <URegistrar.h>
  27. #include <LEditField.h>
  28. #include <iostream>
  29. #include <sioux.h>
  30. #include <stdio.h>
  31. #include <UModalDialogs.h>
  32. #include <LArrayIterator.h>
  33. #include <LString.h>
  34.  
  35. #include <OpenTptAppleTalk.h>
  36.  
  37. #include <NetSprocket.h>
  38.  
  39. // put declarations for resource ids (ResIDTs) here
  40.  
  41. const CommandT    cmd_Advertise            = 2000;
  42. const CommandT    cmd_Join                = 2001;
  43. const CommandT    cmd_Unadvertise            = 2002;
  44. const CommandT    cmd_Start                = 2003;
  45.  
  46. enum {kKeyboardState = 600, kGameStart, kGameEnd};
  47. Boolean IsPressed(unsigned short k);
  48. // ===========================================================================
  49. //        • Main Program
  50. // ===========================================================================
  51.  
  52. void main(void)
  53. {
  54.     SIOUXSettings.autocloseonquit = true;
  55.     SIOUXSettings.asktosaveonclose = true;
  56.     SIOUXSettings.initializeTB = false;
  57.     SIOUXSettings.setupmenus = false;
  58.     SIOUXSettings.standalone = false;
  59.                                     // Set Debugging options
  60.     SetDebugThrow_(debugAction_SourceDebugger);
  61.     SetDebugSignal_(debugAction_SourceDebugger);
  62.     InitializeHeap(3);                // Initialize Memory Manager
  63.                                     // Parameter is number of Master Pointer
  64.                                     //   blocks to allocate
  65.     
  66.                                     // Initialize standard Toolbox managers
  67.     UQDGlobals::InitializeToolbox(&qd);
  68.             
  69.     new LGrowZone(20000);            // Install a GrowZone function to catch
  70.                                     //    low memory situations.
  71.     PPTestApp    theApp;            // replace this with your App type
  72.     
  73.     theApp.Run();
  74. }
  75.  
  76.  
  77. // ---------------------------------------------------------------------------
  78. //        • CPPStarterApp             // replace this with your App type
  79. // ---------------------------------------------------------------------------
  80. //    Constructor
  81.  
  82. PPTestApp::PPTestApp()
  83. {
  84.     // Register functions to create core PowerPlant classes
  85.     bAdvertising = false;
  86.     bRunning = false;
  87.     mPlayerCount = 0;
  88.     theGame = NULL;
  89.     RegisterAllPPClasses();
  90.     URegistrar::RegisterClass(CPlayerWindow::class_ID,        CPlayerWindow::CreatePlayerWindowStream);
  91.     gPulseBit = 0;
  92.     
  93. //    Initialize our player list
  94.     CPlayerListComparator *theComparator = new CPlayerListComparator();
  95.     ThrowIfNULL_(theComparator);
  96.     mPlayerList = new LArray(sizeof(PlayerListItem), theComparator, true);
  97.     ThrowIfNULL_(mPlayerList);
  98.  
  99. }
  100.  
  101.  
  102. // ---------------------------------------------------------------------------
  103. //        • ~PPTestApp            // replace this with your App type
  104. // ---------------------------------------------------------------------------
  105. //    Destructor
  106. //
  107.  
  108. PPTestApp::~PPTestApp()
  109. {
  110. }
  111.  
  112. // ---------------------------------------------------------------------------
  113. //        • StartUp
  114. // ---------------------------------------------------------------------------
  115. //    This function lets you do something when the application starts up. 
  116. //    For example, you could issue your own new command, or respond to a system
  117. //  oDoc (open document) event.
  118.  
  119. void
  120. PPTestApp::StartUp()
  121. {
  122.     OSStatus err;
  123.     UInt32    choice = 0;
  124.     
  125.     ObeyCommand(cmd_New, nil);        // EXAMPLE, create a new window
  126.     
  127. //    Do some quick and dirty testing
  128.     cout << "Starting up" << endl;
  129.     err =  InitializeNetSprocket(500, 800000, 40);
  130.     cout << "InitializeNetSprocket: " << err << endl;
  131.  
  132. }
  133.  
  134.  
  135. Boolean IsPressed(unsigned short k)
  136. // k =  any keyboard scan code, 0-127
  137. {
  138.     KeyMap map;
  139.     unsigned char km[16];
  140.     
  141.     GetKeys(map);
  142.     BlockMove(map, km, 16);
  143.  
  144.     Boolean pressed;
  145.     pressed = ( ( km[k>>3] >> (k & 7) ) & 1);
  146.     
  147.     return pressed;
  148. }
  149. int gLastTickCount = 0;
  150.  
  151. void
  152. PPTestApp::ProcessNextEvent()
  153. {
  154.     EventRecord        macEvent;
  155.     TNetMessageHeader        *theMessage;
  156.     if (IsOnDuty()) {
  157.             
  158.             // Calling OSEventAvail with a zero event mask will always
  159.             // pass back a null event. However, it fills the EventRecord
  160.             // with the information we need to set the cursor shape--
  161.             // the mouse location in global coordinates and the state
  162.             // of the modifier keys.
  163.             
  164.         ::OSEventAvail(0, &macEvent);
  165.         AdjustCursor(macEvent);
  166.     }
  167.     
  168.         // Retrieve the next event. Context switch could happen here.
  169.     
  170.     Boolean    gotEvent = ::WaitNextEvent(everyEvent, &macEvent, 0,
  171.                                         mMouseRgnH);
  172.  
  173.  
  174.     Boolean SIOUXDidEvent = SIOUXHandleOneEvent(&macEvent);
  175.     if (!SIOUXDidEvent)
  176.     {
  177.         SetUpdateCommandStatus(false);
  178.         
  179.             // Let Attachments process the event. Continue with normal
  180.             // event dispatching unless suppressed by an Attachment.
  181.  
  182.         if (LAttachable::ExecuteAttachments(msg_Event, &macEvent)) {
  183.             if (gotEvent) {
  184.                 DispatchEvent(macEvent);
  185.             } else {
  186.                 UseIdleTime(macEvent);
  187.             }
  188.         }
  189.     }
  190.                                         // Repeaters get time after every event
  191.     LPeriodical::DevoteTimeToRepeaters(macEvent);
  192.     
  193.                                     // Update status of menu items
  194.     if (IsOnDuty() && GetUpdateCommandStatus()) {
  195.         UpdateMenus();
  196.     }
  197.     
  198.     if (theGame && bRunning /*&& IsPressed(122)*/)
  199.     {
  200.         UInt32 count = TickCount();
  201.         if (count >= gLastTickCount)
  202.         {    
  203.             TKeyState    state;
  204.             
  205.             gLastTickCount = count + 3;
  206.             
  207.             ClearNetMessageHeader((TNetMessageHeader *)&state);
  208.             state.h.what = kKeyboardState;
  209.             state.h.from = GetMyPlayerID(theGame);
  210.             state.h.to = 0;
  211.             state.h.messageLen = sizeof(TKeyState);
  212.             
  213.             state.keyMap[0] = IsPressed(0x7e) ? 1 : 0;
  214.             state.keyMap[1] = IsPressed(0x7d) ? 1 : 0;
  215.             state.keyMap[2] = IsPressed(0x7c) ? 1 : 0;
  216.             state.keyMap[3] = IsPressed(0x7b) ? 1 : 0;
  217.             state.pulseBit = gPulseBit;
  218.             gPulseBit = (gPulseBit == 1) ? 0 : 1;
  219.             
  220. //            if (state.keyMap[0] != 0)
  221.                 SendNetMessage(theGame, (TNetMessageHeader *) &state, kSelfSend);    
  222.         }    
  223.     }
  224.     
  225.     if (theGame)
  226.     {
  227.         while ((theMessage = GetNextNetMessage(theGame)) != NULL)
  228.         {
  229.             HandleGameEvent(theMessage);
  230.             ReleaseNetMessage(theGame, (TNetMessageHeader *)theMessage);
  231.         }
  232.     }
  233.         
  234. }
  235.  
  236.  
  237. void PPTestApp::HandleGameEvent(TNetMessageHeader *inEvent)
  238. {
  239. #if VERBOSE
  240.     cout << "Handling event:";
  241.     cout << "\twhat = " << inEvent->what << endl;
  242.     cout << "\twhen = " << inEvent->when << endl;
  243.     cout << "\tfrom = " << inEvent->from << endl;
  244.     cout << "\tto = " << inEvent->to << endl;
  245.     cout << "\tid = " << inEvent->id << endl;
  246.     cout << "\tdataLen = " << inEvent->dataLen << endl;
  247.     cout << "\tcookie = " << inEvent->cookie << endl;
  248. #endif
  249.     switch (inEvent->what)
  250.     {
  251.         case kNSJoinApproved:
  252.         break;
  253.         case kNSJoinDenied:
  254.         break;
  255.         case kNSPlayerJoined:
  256.             HandlePlayerJoined((TPlayerJoinedMessage *)inEvent);
  257.         break;
  258.         case kNSPlayerLeft:
  259.             HandlePlayerLeft((TPlayerLeftMessage *)inEvent);
  260.         break;
  261.         case kKeyboardState:
  262.             HandleKeyboardState((TKeyState *)inEvent);
  263.         break;
  264.         case kGameStart:
  265.             HandleGameStart(inEvent);
  266.         break;
  267.         case kGameEnd:
  268.             HandleGameEnd(inEvent);
  269.         break;
  270.         default:
  271.             cout << "Unhandled game event:" << inEvent->what << endl;
  272.         break;
  273.     }
  274. }
  275.  
  276. void PPTestApp::HandlePlayerJoined(TPlayerJoinedMessage *inEvent)
  277. {
  278.     PlayerListItem item;
  279.     TNetMessageHeader    theMessage;
  280.     
  281.     cout << "In HandlePlayerJoined" << endl;
  282.  
  283.     if (bRunning)
  284.     {
  285.         ClearNetMessageHeader(&theMessage);
  286.         theMessage.what = kGameStart;
  287.         theMessage.to = inEvent->playerInfo.id;
  288.         theMessage.messageLen = sizeof(TNetMessageHeader);
  289.         
  290.         SendNetMessage(theGame, &theMessage, kSelfSend);
  291.  
  292.         LWindow *window = LWindow::CreateWindow(1002, this);
  293.         window->SetDescriptor(inEvent->playerInfo.name);
  294.         window->Show();
  295.         item.player = inEvent->playerInfo.id;
  296.         item.window = window;
  297.         mPlayerList->InsertItemsAt(1, 0, &item);
  298.     }
  299.     mPlayerCount++;
  300.     
  301. }
  302.  
  303. void PPTestApp::HandlePlayerLeft(TPlayerLeftMessage *inEvent)
  304. {
  305.     cout << "In HandlePlayerLeft" << endl;
  306.     
  307.     ArrayIndexT    index = mPlayerList->FetchIndexOfKey(&inEvent->playerID);
  308.     PlayerListItem item;
  309.     mPlayerList->FetchItemAt(index, &item);
  310.     item.window->DoClose();
  311.     
  312.     mPlayerCount--;
  313. }
  314.  
  315. void PPTestApp::HandleGameStart(TNetMessageHeader *inEvent)
  316. {
  317.     UInt32    i;
  318.     LWindow    *window;
  319.     bRunning = true;
  320.     PlayerListItem item;
  321.     LStr255    title;
  322.     OSStatus    err;
  323.     
  324.     TPlayersPtr     thePlayers;
  325.     TPlayerInfoPtr    playerInfo;
  326.             
  327.     err = GetPlayers(theGame, &thePlayers);
  328.     if (err == kNSNoError)
  329.     {
  330.         for (i = 0; i < thePlayers->count; i++)
  331.         {
  332.             playerInfo = thePlayers->playerInfo[i];
  333.             window = LWindow::CreateWindow(1002, this);
  334.             window->SetDescriptor(playerInfo->name);
  335.             window->Show();
  336.             item.player = playerInfo->id;
  337.             item.window = window;
  338.             
  339.             mPlayerList->InsertItemsAt(1, 0, &item);
  340.             
  341.         }
  342.         
  343.         ReleasePlayers(theGame, thePlayers);
  344.     }
  345.     else
  346.         cout << "GetPlayers returned " << err << endl;
  347. }
  348.  
  349. void PPTestApp::HandleGamePause(TNetMessageHeader *inEvent)
  350. {
  351.     cout << "In HandleGamePause" << endl;
  352. }
  353.  
  354. void PPTestApp::HandleGameEnd(TNetMessageHeader *inEvent)
  355. {
  356.     cout << "In HandleGameEnd" << endl;
  357.     PlayerListItem item;
  358.     LArrayIterator     iter(*mPlayerList);
  359.     
  360.     while(iter.Next(&item))
  361.     {
  362.         item.window->DoClose();
  363.         mPlayerList->Remove(&item);
  364.     }
  365.     
  366.     bRunning = false;
  367.     OSStatus err = DeleteGame(theGame, 0);
  368.     theGame = NULL;
  369. }
  370.  
  371. void PPTestApp::HandleKeyboardState(TKeyState *inEvent)
  372. {
  373.     PlayerListItem info;
  374.     ArrayIndexT    index;
  375.             
  376.     index = mPlayerList->FetchIndexOfKey(&inEvent->h.from);
  377. #if DEBUG
  378.     if (index == LArray::index_Bad)
  379.         cout << "Got a bad player list index in HandleKeyboardState" << endl;
  380. #endif
  381.     if (mPlayerList->FetchItemAt(index, &info))
  382.     {
  383.         CPlayerWindow *theWindow = (CPlayerWindow *)info.window;
  384.         
  385.         if (theWindow)
  386.         {
  387.             theWindow->mUp = inEvent->keyMap[0];
  388.             theWindow->mDown = inEvent->keyMap[1];
  389.             theWindow->mLeft = inEvent->keyMap[2];
  390.             theWindow->mRight = inEvent->keyMap[3];
  391.             theWindow->mPulse = inEvent->pulseBit;
  392.             
  393.             theWindow->Refresh();
  394.         }
  395.     }
  396. }
  397.  
  398.  
  399. // ---------------------------------------------------------------------------
  400. //        • ObeyCommand
  401. // ---------------------------------------------------------------------------
  402. //    Respond to commands
  403.  
  404. Boolean
  405. PPTestApp::ObeyCommand(
  406.     CommandT    inCommand,
  407.     void        *ioParam)
  408. {
  409.     Boolean        cmdHandled = true;
  410.     OSErr        err;
  411.     Str255 name;
  412.     Str255 password;
  413.     Str255 gameName;
  414.     UInt16    port = 3333;
  415.     TNetMessageHeader theMessage;
  416.     
  417.     switch (inCommand) {
  418.     
  419.         // Deal with command messages (defined in PP_Messages.h).
  420.         // Any that you don't handle will be passed to LApplication
  421.              
  422.         case cmd_Advertise:
  423.         {
  424.             UInt32 protocols = 0;
  425.             LString::CopyPStr("\pTest1", gameName);
  426.             LString::CopyPStr("\pbarney", password);
  427.             LString::CopyPStr("\pDarmok", name);
  428.  
  429.             protocols = DoModalHostDialog("\pChoose your poison:", &port, gameName, name, password);
  430.                 
  431.             cout << "DoModalAdvertiseDialog returned a protocol list of " << protocols << endl;
  432.  
  433.             if (protocols == 0)
  434.                 break;
  435.                 
  436.             err = NewGame(&theGame, 12, gameName, password, name, 0, kNSClientServer, 0);
  437.             if (err != kNSNoError)
  438.             {
  439.                 cout << "NewGame returned an error! " << err << endl;
  440.                 return true;
  441.             }
  442.             mPlayerCount++;
  443.             if (protocols & kAppleTalk)
  444.             {
  445.                     err = HostGameOnAppleTalk(theGame, "\pbandersnatch", 0);
  446.                     cout << "HostGame on AppleTalk (expect 0): " << err << endl;
  447.             }
  448.             if (protocols & kTCPIP)
  449.             {
  450.                     err = HostGameOnTCPIP(theGame, &port, 0);
  451.                     cout << "HostGame on TCP/IP (expect 0): " << err << endl;
  452.             }
  453.             if (protocols & kSerial)
  454.             {
  455.                     cout << "Serial Not implemented" << err << endl;
  456.             }
  457.             bAdvertising = true;
  458.             bHost = true;
  459.         }
  460.         break;
  461.         case cmd_Unadvertise:
  462.             if (bAdvertising)
  463.             {
  464.                 err = StopHostingAppleTalk(theGame);
  465.                 cout << "StopHostingGame game (expect 0): " << err << endl;
  466.                 if (err == noErr)
  467.                     bAdvertising = false;
  468.             }
  469.         break;
  470.         case cmd_Join:
  471.         {
  472.             TGameAddressRef theAddress;
  473.             LString::CopyPStr("\pDarmok", name);
  474.             LString::CopyPStr("\pbarney", password);
  475.  
  476.             theAddress = DoModalJoinDialog("\pbandersnatch", "\pGame servers:", name, password);
  477.             cout << "DoModalJoinWithName returned an address ref of " << theAddress << endl;
  478.             if (theAddress != NULL)
  479.             {
  480.                 err = JoinGame(&theGame, theAddress, name, password, 0, 0, NULL,0);
  481.                 cout << "JoinGame returned err: " << err << endl;
  482.                 ReleaseGameAddressRef(theAddress);
  483.             }
  484.             bHost = false;
  485.             bAdvertising = false;
  486.         }
  487.         break;
  488.         case cmd_Start:
  489.             ClearNetMessageHeader(&theMessage);
  490.             theMessage.what = kGameStart;
  491.             theMessage.to = 0;
  492.             theMessage.messageLen = sizeof(TNetMessageHeader);
  493.             
  494.             SendNetMessage(theGame, &theMessage, kSelfSend);
  495. //            bRunning = true;
  496.             
  497.         break;
  498.         case cmd_Quit:
  499.             if (theGame)
  500.             {
  501.                 if (bHost)
  502.                 {
  503.                     ClearNetMessageHeader(&theMessage);
  504.                     theMessage.what = kGameEnd;
  505.                     theMessage.to = 0;
  506.                     theMessage.messageLen = sizeof(TNetMessageHeader);
  507.                     
  508.                     SendNetMessage(theGame, &theMessage, 0);
  509.                 }
  510.                 DeleteGame(theGame, kNSForceTerminateGame);
  511.                 theGame = NULL;
  512.             }
  513.             bRunning = false;
  514.             LApplication::ObeyCommand(inCommand, ioParam);
  515.         default:
  516.             cmdHandled = LApplication::ObeyCommand(inCommand, ioParam);
  517.             break;
  518.     }
  519.     
  520.     return cmdHandled;
  521. }
  522.  
  523. // ---------------------------------------------------------------------------
  524. //        • FindCommandStatus
  525. // ---------------------------------------------------------------------------
  526. //    This function enables menu commands.
  527. //
  528.  
  529. void
  530. PPTestApp::FindCommandStatus(
  531.     CommandT    inCommand,
  532.     Boolean        &outEnabled,
  533.     Boolean        &outUsesMark,
  534.     Char16        &outMark,
  535.     Str255        outName)
  536. {
  537.  
  538.     switch (inCommand) {
  539.     
  540.         // Return menu item status according to command messages.
  541.         // Any that you don't handle will be passed to LApplication
  542.  
  543.         case cmd_Advertise:
  544.             outEnabled = true;
  545.         break;
  546.         case cmd_Unadvertise:
  547.             if (bAdvertising == true)
  548.                 outEnabled = true;
  549.             else
  550.                 outEnabled = false;
  551.         break;
  552.         case cmd_Join:
  553.             outEnabled = true;
  554.         break;
  555.         case cmd_Start:
  556.                 outEnabled = true;
  557.         break;
  558.         default:
  559.             LApplication::FindCommandStatus(inCommand, outEnabled,
  560.                                                 outUsesMark, outMark, outName);
  561.             break;
  562.     }
  563. }
  564.  
  565.  
  566. Int32
  567. CPlayerListComparator::Compare(
  568.     const void*        inItemOne,
  569.     const void*        inItemTwo,
  570.     Uint32            /* inSizeOne */,
  571.     Uint32            /* inSizeTwo */) const
  572. {
  573.     return ( (((PlayerListItem *)inItemOne)->player) - (((PlayerListItem *)inItemTwo)->player) );
  574. }
  575.  
  576.  
  577. Boolean
  578. CPlayerListComparator::IsEqualTo(
  579.     const void*        inItemOne,
  580.     const void*        inItemTwo,
  581.     Uint32            /* inSizeOne */,
  582.     Uint32            /* inSizeTwo */) const
  583. {
  584.     return ( (((PlayerListItem *)inItemOne)->player) == (((PlayerListItem *)inItemTwo)->player) );
  585. }
  586.  
  587.  
  588. Int32
  589. CPlayerListComparator::CompareToKey(
  590.     const void*         inItem ,
  591.     Uint32            /* inSize */,
  592.     const void*         inKey ) const
  593. {
  594.     return ( (((PlayerListItem *)inItem)->player) - (*(TPlayerID *)inKey) );
  595. }
  596.                                 
  597.  
  598. Boolean
  599. CPlayerListComparator::IsEqualToKey(
  600.     const void*        inItem,
  601.     Uint32            inSize,
  602.     const void*        inKey) const
  603. {
  604.     return ( (((PlayerListItem *)inItem)->player) == (*(TPlayerID *)inKey) );
  605. }
  606.